Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-63343] Validate element types for collections and maps when deserializing XML files #9727

Merged
merged 14 commits into from
Oct 11, 2024

Conversation

dwnusbaum
Copy link
Member

@dwnusbaum dwnusbaum commented Sep 12, 2024

See JENKINS-63343. This PR checks all fields being deserialized to see if they will be handled by RobustCollectionConverter or RobustMapConverter, and if so, it explicitly constructs an instance of the converter specialized to the type of the field in question so that collection elements and map keys and values can be type checked. Any values which do not have the expected type are ignored, and an OldDataMonitor warning is logged.

Testing done

See new automated tests.

Proposed changelog entries

  • Ignore values with incorrect types when deserializing collections and maps in XML files.

Proposed upgrade guidelines

N/A

Submitter checklist

Desired reviewers

@mention

Before the changes are marked as ready-for-merge:

Maintainer checklist

Comment on lines 454 to 457
// TODO: Is there a better way to make something like this work? Does it break any custom converters?
if (converter == null && new RobustCollectionConverter(mapper, reflectionProvider).canConvert(type)) {
converter = new RobustCollectionConverter(mapper, reflectionProvider, field.getGenericType());
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular I am wondering about things like NodeList and AxisList which extend ArrayList. They might be ok because of the exact equality comparisons here, but I am not sure. I guess also that those classes don't support any of the desired recoverability features in RobustCollectionConverter, but that shouldn't be affected by my PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirmed that NodeList is unaffected by this change - its custom converter continues to be used and its deserialization is not robust against invalid values.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at #342, I think we only expect getLocalConverter to matter for fields that have the @XStreamConverter annotation, which seems to be more or less unused based on this search, and also none of those annotations are for collections or maps.

@@ -451,6 +451,13 @@ private boolean fieldDefinedInClass(Object result, String attrName) {

protected Object unmarshalField(final UnmarshallingContext context, final Object result, Class type, Field field) {
Converter converter = mapper.getLocalConverter(field.getDeclaringClass(), field.getName());
if (converter == null) {
if (new RobustCollectionConverter(mapper, reflectionProvider).canConvert(type)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit awkward to recreate this for every single field being unmarshalled, should we keep an instance as a local field just for these canConvert calls?

@@ -451,6 +451,13 @@ private boolean fieldDefinedInClass(Object result, String attrName) {

protected Object unmarshalField(final UnmarshallingContext context, final Object result, Class type, Field field) {
Converter converter = mapper.getLocalConverter(field.getDeclaringClass(), field.getName());
if (converter == null) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #9727 (comment) for discussion about cases where converter is not null. In short, I don't think we care.

I am not sure though whether this method covers all of the cases we care about. It seems like we may need similar changes related to "implicit collections". I will look into that a bit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, prior to this line, I think we should look up the field and then add code comparable to what we added to RobustCollectionConverter to validate the value type:

Needs to be investigated with a test case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into the cases related to implicit collections today. My understanding is that you need to explicitly call addImplicitArray, addImplicitCollection, or addImplicitMap for the relevant code to matter, which is not very common, see here (there are also a few usages in CloudBees plugins). The overloads where you specify the item type already avoid JENKINS-63343 because of getFieldNameForItemTypeAndName here which uses context.getRequiredType() leading to invalid elements being silently ignored. The overloads for arrays and maps seem to not actually work at all due to this check (which leaves me somewhat confused about #2621, but perhaps my testing did not cover all cases).

So, I think we do not really care much about implicit collections, but 09ca355 should handle them too.

@dwnusbaum dwnusbaum changed the title [JENKINS-63343] Validate element types in RobustCollectionConverter in some cases [JENKINS-63343] Validate element types for collections and maps during XML deserialization in some cases Sep 23, 2024
@dwnusbaum dwnusbaum changed the title [JENKINS-63343] Validate element types for collections and maps during XML deserialization in some cases [JENKINS-63343] Validate element types for collections and maps during XML deserialization Sep 23, 2024
@dwnusbaum dwnusbaum changed the title [JENKINS-63343] Validate element types for collections and maps during XML deserialization [JENKINS-63343] Validate element types for collections and maps when deserializing XML files Sep 23, 2024
@dwnusbaum dwnusbaum added the bug For changelog: Minor bug. Will be listed after features label Sep 23, 2024
@dwnusbaum dwnusbaum marked this pull request as ready for review September 23, 2024 19:37
Copy link
Member

@jglick jglick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments, but generally looks good to the extent I understand it; I definitely do not follow all the subtleties about XStream behavior.

@dwnusbaum
Copy link
Member Author

/label ready-for-merge


This PR is now ready for merge, after ~24 hours, we will merge it if there's no negative feedback.

Thanks!

@comment-ops-bot comment-ops-bot bot added the ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback label Oct 8, 2024
@dwnusbaum dwnusbaum merged commit 6651e85 into jenkinsci:master Oct 11, 2024
16 checks passed
@dwnusbaum dwnusbaum deleted the JENKINS-63343 branch October 11, 2024 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug For changelog: Minor bug. Will be listed after features ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants